home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 4
/
Aminet 4 - November 1994.iso
/
aminet
/
comm
/
term
/
term41source.lha
/
Extras
/
Source
/
term-Source.lha
/
termIdentify.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-14
|
17KB
|
906 lines
/*
** termIdentify.c
**
** Heuristic file type identification routines (big words!).
**
** Copyright © 1990-1994 by Olaf `Olsen' Barthel
** All Rights Reserved
*/
#include "termGlobal.h"
/* The file types we know. */
enum { TYPE_DIR,TYPE_FILE,
TYPE_ICON,
TYPE_TEXT,
TYPE_C,TYPE_H,
TYPE_ASM,TYPE_I,
TYPE_MOD,
TYPE_REXX,
TYPE_BASIC,
TYPE_AMIGAGUIDE,
TYPE_TEX,TYPE_METAFONT,TYPE_GF,TYPE_TEXFONT,TYPE_TEXDVI,TYPE_FLIB,
TYPE_OLDMANX,TYPE_NEWMANX,TYPE_OLDMANXLIB,TYPE_NEWMANXLIB,
TYPE_OBJECT,TYPE_LIB,
TYPE_EXECUTABLE,
TYPE_LIBRARY,TYPE_DEVICE,TYPE_FILESYS,TYPE_HANDLER,
TYPE_GIF,TYPE_DEGAS,TYPE_MACPAINT,TYPE_SUPERPAINT,TYPE_PICT,TYPE_SUNRASTER,TYPE_POSTSCRIPT,TYPE_PCX,TYPE_TIFF,TYPE_BMP,TYPE_JFIF,TYPE_ILBM,
TYPE_ANIM,TYPE_8SVX,TYPE_SMUS,TYPE_FTXT,TYPE_PREFS,TYPE_TERM,TYPE_AMIGAVISION,TYPE_IFF,
TYPE_IMPLODER,TYPE_POWERPACKER,TYPE_LHPAK,TYPE_LHASFX,
TYPE_ARC,TYPE_ARJ,TYPE_COMPRESSED,TYPE_CPIO,TYPE_UUENCODED,TYPE_FREEZE,TYPE_MACCOMPRESS,TYPE_COMPACT,TYPE_DIAMOND,TYPE_LHARC,TYPE_LHA,TYPE_ZOO,TYPE_ZIP,TYPE_STUFFIT,TYPE_PACKIT,TYPE_DMS,TYPE_WARP,TYPE_ZOOM,
TYPE_SPARCOBJECT,TYPE_SPARCEXECUTABLE,
TYPE_MSDOSEXECUTABLE,
TYPE_ATARIEXECUTABLE,
TYPE_MACEXECUTABLE,
TYPE_CDAF,TYPE_XPK,
TYPE_COUNT
};
/* File type/class mappings. */
STATIC WORD FileTypes[TYPE_COUNT] =
{
FILETYPE_DIR,
FILETYPE_FILE,
FILETYPE_NONE,
FILETYPE_TEXT,
FILETYPE_TEXT,
FILETYPE_TEXT,
FILETYPE_TEXT,
FILETYPE_TEXT,
FILETYPE_TEXT,
FILETYPE_TEXT,
FILETYPE_TEXT,
FILETYPE_TEXT,
FILETYPE_TEXT,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_PROGRAM,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_PICTURE,
FILETYPE_SOUND,
FILETYPE_SOUND,
FILETYPE_TEXT,
FILETYPE_PREFS,
FILETYPE_PREFS,
FILETYPE_FILE,
FILETYPE_FILE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_TEXT,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE,
FILETYPE_PROGRAM,
FILETYPE_PROGRAM,
FILETYPE_PROGRAM,
FILETYPE_PROGRAM,
FILETYPE_PROGRAM,
FILETYPE_ARCHIVE,
FILETYPE_ARCHIVE
};
/* File class icon names. */
STATIC STRPTR ClassIconNames[FILETYPE_COUNT] =
{
NULL,
"ENV:sys/def_drawer",
"ENV:sys/def_project",
"ENV:sys/def_text",
"ENV:sys/def_sound",
"ENV:sys/def_picture",
"ENV:sys/def_pref",
"ENV:sys/def_archive",
"ENV:sys/def_tool",
};
/* A structure containing both a file name suffix and the
* approriate file type.
*/
struct Suffix
{
UBYTE *Name;
UBYTE Type;
};
/* A table of valid ASCII characters (7 bits). */
STATIC BYTE ID_ValidTab[256] =
{
0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,
0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
/* A table of clearly invalid ASCII characters (8 bits). */
STATIC BYTE ID_InvalidTab[256] =
{
1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,
1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
/* Some file name suffixes for text files and the approriate
* file types.
*/
STATIC struct Suffix TextSuffix[] =
{
".C", TYPE_C,
".CPP", TYPE_C,
".CXX", TYPE_C,
".C++", TYPE_C,
".CC", TYPE_C,
".H", TYPE_H,
".ASM", TYPE_ASM,
".A", TYPE_ASM,
".S", TYPE_ASM,
".I", TYPE_I,
".BAS", TYPE_BASIC,
".GFA", TYPE_BASIC,
".REXX", TYPE_REXX,
".CED", TYPE_REXX,
".TTX", TYPE_REXX,
".VLT", TYPE_REXX,
".CPR", TYPE_REXX,
".TxEd", TYPE_REXX,
".ADPro", TYPE_REXX,
".TEX", TYPE_TEX,
".STY", TYPE_TEX,
".MF", TYPE_METAFONT,
".MOD", TYPE_MOD,
".DEF", TYPE_MOD,
".PS", TYPE_POSTSCRIPT,
".GUIDE", TYPE_AMIGAGUIDE,
".UUE", TYPE_UUENCODED
};
/* Some more file name suffixes for executable files and the
* approriate file types.
*/
STATIC struct Suffix ExecutableSuffix[] =
{
".device", TYPE_DEVICE,
".library", TYPE_LIBRARY,
"FileSystem", TYPE_FILESYS,
"Handler", TYPE_HANDLER
};
/* Miscellaneous magic cookies. */
STATIC STRPTR MagicCookies[] =
{
"P1",
"P2",
"P3",
"P4",
"P5",
"P6",
"begin",
"xbtoa"
};
/* LongCompare(UBYTE *Buffer,ULONG Value):
*
* Compare space in memory with a longword value.
*/
STATIC BYTE __regargs
LongCompare(UBYTE *Buffer,ULONG Value)
{
UBYTE *OtherBuffer = (UBYTE *)&Value,i;
for(i = 0 ; i < 4 ; i++)
{
if(OtherBuffer[i] != Buffer[i])
return(FALSE);
}
return(TRUE);
}
/* GetFileType(STRPTR Name,BYTE AttachComment):
*
* Simple routine to identify a file type by looking at
* its first 400 bytes. If successful a comment is
* attached to the file describing the file type.
*/
WORD __regargs
GetFileType(STRPTR Name,BYTE AttachComment)
{
ULONG *Buffer;
UBYTE Type = TYPE_FILE,
*TypeName = NULL;
WORD i,
Len = strlen(Name);
UBYTE IFFType[5];
/* Allocate a buffer for the first 410 bytes of the
* file.
*/
if(Buffer = (ULONG *)AllocVecPooled(410,MEMF_ANY | MEMF_CLEAR))
{
BPTR File,Size;
/* Open the file. */
if(File = Open(Name,MODE_OLDFILE))
{
/* Read the first 410 bytes. */
if((Size = Read(File,Buffer,410)) >= sizeof(ULONG))
{
UBYTE *CharBuffer = (UBYTE *)Buffer;
WORD Count = 0;
/* See if it's an ASCII file. */
for(i = 0 ; i < Size ; i++)
{
if(ID_ValidTab[CharBuffer[i]])
Count++;
else
{
if(ID_InvalidTab[CharBuffer[i]])
{
Count = 0;
break;
}
}
}
/* If more than 75% of the
* characters in the first
* 400 bytes are legal
* ASCII characters this
* file is supposed to be
* a text file.
*/
if(Count > 3 * (Size / 4))
Type = TYPE_TEXT;
/* Examine the first longword. */
if(Type == TYPE_FILE)
{
switch(Buffer[0])
{
case 0x58504B46:
Type = TYPE_XPK;
break;
case 0x000003E7:
Type = TYPE_OBJECT;
break;
case 0x000003F3:
if(Buffer[10] == 'LSFX')
Type = TYPE_LHPAK;
else
{
if(Buffer[11] == 'SFX!')
Type = TYPE_LHASFX;
else
Type = TYPE_EXECUTABLE;
}
break;
case 0x000003FA:
Type = TYPE_LIB;
break;
case 0xF7593647:
Type = TYPE_TEXFONT;
break;
case 0xF7020183:
Type = TYPE_TEXDVI;
break;
case 0xF7832020:
Type = TYPE_GF;
break;
case 0x504B0304:
Type = TYPE_ZIP;
break;
case 0x01030107:
Type = TYPE_SPARCOBJECT;
break;
case 0x8103010B:
Type = TYPE_SPARCEXECUTABLE;
break;
case 0x59A66A95:
Type = TYPE_SUNRASTER;
break;
case 0x1F9D902A:
Type = TYPE_COMPRESSED;
break;
case 0x30373037:
Type = TYPE_CPIO;
break;
case 'FLIB':
Type = TYPE_FLIB;
break;
case 'FORM':
switch(Buffer[2])
{
case 'ILBM':
Type = TYPE_ILBM;
break;
case 'ANIM':
Type = TYPE_ANIM;
break;
case '8SVX':
Type = TYPE_8SVX;
break;
case 'SMUS':
Type = TYPE_SMUS;
break;
case 'FTXT':
Type = TYPE_FTXT;
break;
case 'PREF':
Type = TYPE_PREFS;
break;
case 'TERM':
Type = TYPE_TERM;
break;
case 'AVCF':
Type = TYPE_AMIGAVISION;
break;
case 'CDAF':
Type = TYPE_CDAF;
break;
default:
Type = TYPE_IFF;
CopyMem(&Buffer[2],IFFType,4);
IFFType[4] = 0;
break;
}
break;
case 'IMP!':
Type = TYPE_IMPLODER;
break;
case 'PP20':
Type = TYPE_POWERPACKER;
break;
case 'DMS!':
Type = TYPE_DMS;
break;
case 'Warp':
Type = TYPE_WARP;
break;
case 'ZOM5':
case 'ZOOM':
Type = TYPE_ZOOM;
break;
case 'ZOO ':
Type = TYPE_ZOO;
break;
case 'GIF8':
Type = TYPE_GIF;
break;
}
}
/* Now for oddly placed magic cookies... */
if(Type == TYPE_FILE)
{
/* Dumb check for PCX (awful header -- just
* a single byte indicates that the file
* is supposed to be a PCX file! Those
* PC guys just don't have any
* decent software culture!).
*/
if(CharBuffer[0] == 0x0A)
Type = TYPE_PCX;
/* Yet another awful file format... */
if(CharBuffer[0] == 'B' && CharBuffer[1] == 'M')
Type = TYPE_BMP;
/* Check for JFIF... */
if(LongCompare(&CharBuffer[6],'JFIF'))
Type = TYPE_JFIF;
/* Check for `freeze' output file. */
if(CharBuffer[0] == (UBYTE)'\037' && CharBuffer[1] >= (UBYTE)'\236')
Type = TYPE_FREEZE;
}
/* Check for Macintosh data (note:
* this code assumes that the Mac
* binary header is still present,
* so if you are dealing with stripped
* binary files, don't expect the
* following code to work!).
*/
if(Type == TYPE_FILE)
{
UBYTE *ByteBuffer = &((UBYTE *)Buffer)[65];
/* Check for MacPaint... */
if(LongCompare(ByteBuffer,'PNTG'))
Type = TYPE_MACPAINT;
/* Check for SuperPaint... */
if(LongCompare(ByteBuffer,'SPTG'))
Type = TYPE_SUPERPAINT;
/* Check for PICT... */
if(LongCompare(ByteBuffer,'PICT'))
Type = TYPE_PICT;
/* Check for executable... */
if(LongCompare(ByteBuffer,'APPL') || LongCompare(ByteBuffer,'PRES') || LongCompare(ByteBuffer,'FDOC') || LongCompare(ByteBuffer,'cdev') || LongCompare(ByteBuffer,'INIT'))
Type = TYPE_MACEXECUTABLE;
/* Check for StuffIt archive... */
if(LongCompare(ByteBuffer,'SIT!') || LongCompare(ByteBuffer,'SIT2'))
Type = TYPE_STUFFIT;
/* Check for PackIt archive... */
if(LongCompare(ByteBuffer,'PIT '))
Type = TYPE_PACKIT;
/* Check for self-extracting Compact archive. */
if(LongCompare(ByteBuffer,'APPL') && LongCompare(&ByteBuffer[4],'EXTR'))
Type = TYPE_COMPACT;
/* Check for MacCompress archive. */
if(LongCompare(ByteBuffer,'ZIVM'))
Type = TYPE_MACCOMPRESS;
/* Check for LhArc archive with MacBinary header. */
if(LongCompare(ByteBuffer,'LARC'))
Type = TYPE_LHARC;
/* Check for Compact archive. */
if(LongCompare(ByteBuffer,'PACT'))
Type = TYPE_COMPACT;
/* Check for Diamond archive. */
if(LongCompare(ByteBuffer,'Pack'))
Type = TYPE_DIAMOND;
}
/* Still no match? Have another try... */
if(Type == TYPE_FILE)
{
if((Buffer[0] & 0x0000FFFF) == 0x00002D6C && (Buffer[1] & 0xFF00FF00) == 0x68002D00)
{
if(CharBuffer[5] == '5')
Type = TYPE_LHA;
else
Type = TYPE_LHARC;
}
else
{
switch(Buffer[0] & 0xFFFF0000)
{
case 0x4D4D0000:
case 0x49490000:
Type = TYPE_TIFF;
break;
case 0x1A080000:
Type = TYPE_ARC;
break;
case 0x60EA0000:
Type = TYPE_ARJ;
break;
case 0x434A0000:
Type = TYPE_NEWMANX;
break;
case 0x414A0000:
Type = TYPE_OLDMANX;
break;
case 0x636A0000:
Type = TYPE_NEWMANXLIB;
break;
case 0x616A0000:
Type = TYPE_OLDMANXLIB;
break;
case 0xF5000000:
Type = TYPE_BASIC;
break;
case 0xE3100000:
Type = TYPE_ICON;
break;
case 0x4D5A0000:
Type = TYPE_MSDOSEXECUTABLE;
break;
case 0x601A0000:
Type = TYPE_ATARIEXECUTABLE;
break;
case 0x80000000:
Type = TYPE_DEGAS;
break;
}
}
}
/* Take a look at the file name
* suffixes.
*/
switch(Type)
{
case TYPE_TEXT:
for(i = 0 ; i < sizeof(TextSuffix) / sizeof(struct Suffix) ; i++)
{
Size = strlen(TextSuffix[i] . Name);
if(Len >= Size)
{
if(!Stricmp(&Name[Len - Size],TextSuffix[i] . Name))
{
Type = TextSuffix[i] . Type;
break;
}
}
}
/* Is it still a text file? */
if(Type == TYPE_TEXT)
{
/* Check for magic cookies. */
for(i = 0 ; i < sizeof(MagicCookies) / sizeof(STRPTR) ; i++)
{
if(!memcmp(CharBuffer,MagicCookies[i],strlen(MagicCookies[i])))
{
TypeName = LocaleString(MSG_IDENTIFY_COOKIE_0 + i);
break;
}
}
}
break;
case TYPE_EXECUTABLE:
for(i = 0 ; i < sizeof(ExecutableSuffix) / sizeof(struct Suffix) ; i++)
{
Size = strlen(ExecutableSuffix[i] . Name);
if(Len >= Size)
{
if(!Stricmp(&Name[Len - Size],ExecutableSuffix[i] . Name))
{
Type = ExecutableSuffix[i] . Type;
break;
}
}
}
break;
case TYPE_OBJECT:
if(Len >= 4)
{
if(!Stricmp(&Name[Len - 4],".LIB"))
Type = TYPE_LIB;
}
break;
}
}
Close(File);
}
FreeVecPooled(Buffer);
}
if(AttachComment)
{
if(Type > TYPE_FILE || TypeName)
{
if(Type == TYPE_IFF)
{
UBYTE NameBuffer[40];
SPrintf(NameBuffer,LocaleString(MSG_IDENTIFY_IFF_FILE),IFFType);
SetComment(Name,NameBuffer);
}
else
{
if(TypeName)
SetComment(Name,TypeName);
else
SetComment(Name,LocaleString(MSG_IDENTIFY_FILETYPE_0 + Type - TYPE_ICON));
}
}
/* Is it an executable file? */
if(Type != TYPE_EXECUTABLE && Type != TYPE_LHPAK && Type != TYPE_LHASFX)
{
BPTR FileLock;
/* Get a lock on it. */
if(FileLock = Lock(Name,ACCESS_WRITE))
{
struct FileInfoBlock *FileInfo;
/* Allocate fileinfo data. */
if(FileInfo = (struct FileInfoBlock *)AllocDosObjectTags(DOS_FIB,TAG_DONE))
{
/* Take a closer look at it... */
if(Examine(FileLock,FileInfo))
{
/* Release the lock. */
UnLock(FileLock);
/* Really drop it. */
FileLock = NULL;
/* Update protection bits. */
SetProtection(Name,FileInfo -> fib_Protection | FIBF_EXECUTE);
}
/* Free fileinfo data. */
FreeDosObject(DOS_FIB,FileInfo);
}
}
/* Release the lock if still allocated. */
if(FileLock)
UnLock(FileLock);
}
}
return(Type);
}
/* Identify(STRPTR Name):
*
* Try to identify the type of a file,
* attach an icon if necessary.
*/
VOID __regargs
Identify(STRPTR Name,BYTE AttachComment)
{
WORD Type = GetFileType(Name,AttachComment);
if(Config -> MiscConfig -> CreateIcons)
AddIcon(Name,FileTypes[Type],FALSE);
}
/* AddIcon(STRPTR Name,WORD Type,BYTE Override):
*
* Add an icon to a file.
*/
VOID __regargs
AddIcon(STRPTR Name,WORD Index,BYTE Override)
{
if(ClassIconNames[Index] && IconBase)
{
struct DiskObject *Icon;
if(!Override)
{
if(Icon = GetDiskObject(Name))
{
FreeDiskObject(Icon);
return;
}
}
if(!(Icon = GetDiskObject(ClassIconNames[Index])))
{
if(Index == FILETYPE_PROGRAM)
Icon = GetDefDiskObject(WBTOOL);
else
{
AddProtection(Name,FIBF_EXECUTE);
Icon = GetDiskObjectNew(Name);
}
}
if(Icon)
{
Icon -> do_CurrentX = Icon -> do_CurrentY = NO_ICON_POSITION;
PutDiskObject(Name,Icon);
FreeDiskObject(Icon);
}
}
}